﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Nop.Core.Domain.Orders;
using Nop.Core.Domain.Payments;
using Nop.Core.Domain.Shipping;

namespace Nop.Services.Orders
{
    public class OrderGroup
    {
        public OrderGroup()
        {
            Orders = new List<Order>();
        }
        /// <summary>
        /// Gets or sets the group identifier 
        /// </summary>
        public Guid OrderGroupGuid { get; set; }

        /// <summary>
        /// Gets the key order of the group
        /// </summary>
        public Order KeyOrder 
        {
            get
            {
                return Orders.First();
            }
        }
        
        /// <summary>
        /// Gets or sets the order subtotal (incl tax)
        /// </summary>
        public decimal OrderSubtotalInclTax
        {
            get
            {
                return Orders.Sum(o => o.OrderSubtotalInclTax);
            }
        }

        /// <summary>
        /// Gets or sets the order subtotal (excl tax)
        /// </summary>
        public decimal OrderSubtotalExclTax
        {
            get
            {
                return Orders.Sum(o => o.OrderSubtotalExclTax);
            }
        }

        /// <summary>
        /// Gets or sets the order subtotal discount (incl tax)
        /// </summary>
        public decimal OrderSubTotalDiscountInclTax
        {
            get
            {
                return Orders.Sum(o => o.OrderSubTotalDiscountInclTax);
            }
        }

        /// <summary>
        /// Gets or sets the order subtotal discount (excl tax)
        /// </summary>
        public decimal OrderSubTotalDiscountExclTax
        {
            get
            {
                return Orders.Sum(o => o.OrderSubTotalDiscountExclTax);
            }
        }

        /// <summary>
        /// Gets or sets the order shipping (incl tax)
        /// </summary>
        public decimal OrderShippingInclTax
        {
            get
            {
                return Orders.Sum(o => o.OrderShippingInclTax);
            }
        }

        /// <summary>
        /// Gets or sets the order shipping (excl tax)
        /// </summary>
        public decimal OrderShippingExclTax
        {
            get
            {
                return Orders.Sum(o => o.OrderShippingExclTax);
            }
        }

        /// <summary>
        /// Gets or sets the payment method additional fee (incl tax)
        /// </summary>
        public decimal PaymentMethodAdditionalFeeInclTax         
        {
            get
            {
                return Orders.Sum(o => o.PaymentMethodAdditionalFeeInclTax);
            }
        }

        /// <summary>
        /// Gets or sets the payment method additional fee (excl tax)
        /// </summary>
        public decimal PaymentMethodAdditionalFeeExclTax
        {
            get
            {
                return Orders.Sum(o => o.PaymentMethodAdditionalFeeExclTax);
            }
        }

        /// <summary>
        /// Gets or sets the order tax
        /// </summary>
        public decimal OrderTax
        {
            get
            {
                return Orders.Sum(o => o.OrderTax);
            }
        }
        /// <summary>
        /// Gets or sets the order discount (applied to order total)
        /// </summary>
        public decimal OrderDiscount
        {
            get
            {
                return Orders.Sum(o => o.OrderDiscount);
            }
        }

        /// <summary>
        /// Gets or sets the order total
        /// </summary>
        public decimal OrderTotal
        {
            get
            {
                return Orders.Sum(o => o.OrderTotal);
            }
        }

        /// <summary>
        /// Gets or sets the refunded amount
        /// </summary>
        public decimal RefundedAmount
        {
            get
            {
                return Orders.Sum(o => o.RefundedAmount);
            }
        }

        /// <summary>
        /// Gets or sets the order status
        /// </summary>
        public OrderStatus OrderStatus
        {
            get
            {
                //TODO: Handle Cancelled
                if (Orders.All(o => o.OrderStatus == OrderStatus.Pending))
                {
                    return OrderStatus.Pending;
                }
                else if (Orders.All(o => o.OrderStatus == OrderStatus.Complete))
                {
                    return OrderStatus.Complete;
                }
                else if (Orders.All(o => o.OrderStatus == OrderStatus.Cancelled))
                {
                    return OrderStatus.Cancelled;
                }
                else if (Orders.Any(o => o.OrderStatus == OrderStatus.Processing))
                {
                    return OrderStatus.Processing;
                }
                return OrderStatus.Pending;
            }
        }

        /// <summary>
        /// Gets or sets the payment status
        /// </summary>
        public virtual PaymentStatus PaymentStatus
        {
            get
            {
                //Handle Avoid and Authorized
                if (Orders.All(o => o.PaymentStatus == PaymentStatus.Paid))
                {
                    return PaymentStatus.Paid;
                }
                else if (Orders.All(o => o.PaymentStatus == PaymentStatus.Refunded))
                {
                    return PaymentStatus.Refunded;
                }
                else if (Orders.Any(o => o.PaymentStatus == PaymentStatus.Refunded || o.PaymentStatus == PaymentStatus.PartiallyRefunded))
                {
                    return PaymentStatus.PartiallyRefunded;
                }
                return PaymentStatus.Pending;
            }

        }

        /// <summary>
        /// Gets or sets the shipping status
        /// </summary>
        public virtual ShippingStatus ShippingStatus
        {
            get
            {
                if (Orders.All(o => o.ShippingStatus == ShippingStatus.Shipped))
                {
                    return ShippingStatus.Shipped;
                }               
                else if (Orders.All(o => o.ShippingStatus == ShippingStatus.Delivered))
                {
                    return ShippingStatus.Delivered;
                }
                else if (Orders.Any(o => o.ShippingStatus == ShippingStatus.Shipped || o.ShippingStatus == ShippingStatus.PartiallyShipped))
                {
                    return ShippingStatus.PartiallyShipped;
                }
                else if (Orders.All(o => o.ShippingStatus == ShippingStatus.ShippingNotRequired))
                {
                    return ShippingStatus.ShippingNotRequired;
                }
                return ShippingStatus.NotYetShipped;
            }
        }

        public IList<Order> Orders { get; set; }
    }
}
